# -*- coding: utf-8 -*-

import random
import sys
import os

from lts import utils
import lts

class ParserError (Exception):
	"""
		Clase de excepcion del parser.
	"""
	pass

def parse (args_list, minargs, maxargs):
	"""
		Descripcion:
			Funcion encargada de parsear los argumentos de entrada.
		Argumentos:
			args_list	-	Lista de argumentos. Debe ser la lista de argumentos
							recibida en el modulo "__main__" sin el primer 
							elemento (nombre del archivo ejecutado), es deicir, 
							solo los argumentos del programa.
			minargs		-	Es un numero el cual indica la cantidad minima de 
							argumentos que deben ser especificados.
			maxargs		-	Es un numero el cual indica la cantidad maxima de 
							argumentos que deben ser especificados.
		Retorno:
			Una instancia de la clase Dict() con la siguiente estructura.
			Las claves con cadenas de caracteres.
				"system"				->	Lista de instancias de la clase LTS().
				"fault_set"			->	Conjunto de fallas.
				"sync_set"			->	Conjunto de eventos de sincronizacion.
				"graphic"			->	Booleano.
				"heuristic_level"	->	Entero entre 0 y 5.
				"time"				->	Booleano.
				"verbose"			->	Booleano.
				"help"				->	Booleano.
				"mode"				->	Entero entre 0 y 2.
	"""
	# Chequeo la cantidad de argumentos ingresados.
	if len(args_list) < minargs or len(args_list) > maxargs:
		raise ParserError("The number of arguments is incorrect!")
	if len(args_list) == 1 and not '-help' in args_list:
		raise ParserError("The number of arguments is incorrect!")
	if len(args_list) > 1 and '-help' in args_list:
		raise ParserError("The number of arguments is incorrect!")
	# Valor de retorno.
	result = dict()
	result["system"] = []
	result["fault_set"] = set([])
	result["sync_set"] = set([])
	result["graphic"] = False
	result["heuristic_level"] = 0
	result["time"] = False
	result["verbose"] = False
	result["help"] = False
	result["mode"] = 0
	# Recorro la lista de argumentos.
	for arg in args_list:
		if arg.startswith("-s="):
			for s in ((arg.split('='))[1]).split(','):
				if not s:
					raise ParserError("The argument '-s' can not be empty.")
				try:
					result["system"].append(lts.from_file(s))
				except lts.LTSError, (msg,e):
					errmsg = "Error in subsystem: "+str(s)+' - '+msg+' '+e
					raise ParserError(errmsg)
		elif arg.startswith("-f="):
			f_list = ((arg.split('='))[1]).split(',')
			if not f_list or not f_list[0]:
				result["fault_set"] = None
			else:
				for f in f_list:
					if not f.startswith('f'):
						raise ParserError("Incorrect fault name: " + f)
					else:
						result["fault_set"].add(f)
		elif arg.startswith("-c="):
			for e in ((arg.split('='))[1]).split(','):
				if e and not e.startswith('c') and not e.startswith('o'):
					errmsg = "Incorrect synchronization event name: " + e
					raise ParserError(errmsg)
				elif e:
					result["sync_set"].add(e)
		elif arg.startswith("-h="):
			try:
				result["heuristic_level"] = int((arg.split('='))[1])
			except ValueError:
				raise ParserError("Invalid value for arguement '-h'.")
			if result["heuristic_level"] < 0 or result["heuristic_level"] > 6:
				raise ParserError("Values for '-h' go from 0 to 6.")
		elif arg.startswith("-m="):
			try:
				result["mode"] = int((arg.split('='))[1])
			except ValueError:
				raise ParserError("Invalid value for arguement '-m'.")
			if result["mode"] < 0 or result["mode"] > 2:
				raise ParserError("Values for '-m' are 0|1|2.")
		elif arg == "-g":
				result["graphic"] = True
		elif arg == "-t":
			result["time"] = True
		elif arg == "-v":
			result["verbose"] = True
		elif arg == "-help":
			result["help"] = True
		else:
			raise ParserError("Invalid argument: " + arg)
	return result
